package com.abel.quiz.security;/**
 * Created by abel.lin on 2017/8/4.
 */
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;

import com.abel.quiz.po.AuthRolePo;
import com.abel.quiz.services.AuthResourceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
/**
 * @author abel.lin
 * @date_time 2017/8/4 14:42
 * @description
 */
public class MySecurityMetadataSource  implements FilterInvocationSecurityMetadataSource,InitializingBean {


    private static final String AUTH_NO_ROLE =" __AUTH_NO_ROLE__";

    @Autowired
    private AuthResourceService authResourceService;

    public MySecurityMetadataSource(AuthResourceService resourceService) {
        this.authResourceService = resourceService;
    }

    private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    public boolean supports(Class<?> clazz) {
        return true;
    }
    private void loadResourceDefine() {
        if(resourceMap == null) {
            resourceMap = new ConcurrentHashMap<String, Collection<ConfigAttribute>>();
        }else{
            resourceMap.clear();
        }

        Map<String,List<AuthRolePo>> resourceRoleMap = authResourceService.getAllResourceRole();

        for (Entry<String,List<AuthRolePo>> entry : resourceRoleMap.entrySet()) {
            String url = entry.getKey();
            List<AuthRolePo> values = entry.getValue();

            Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();
            for(AuthRolePo secRoleModel : values){
                ConfigAttribute configAttribute = new SecurityConfig(StringUtils.defaultString(secRoleModel.getRoleCode(),AUTH_NO_ROLE));
                configAttributes.add(configAttribute);
            }
            resourceMap.put(url, configAttributes);
        }
    }
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {

        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();

        TreeMap<String, Collection<ConfigAttribute>> attrMap = new TreeMap<String, Collection<ConfigAttribute>>(resourceMap);

        Iterator<String> ite = attrMap.keySet().iterator();

        RequestMatcher urlMatcher = null;

        Collection<ConfigAttribute> attrSet = new HashSet<ConfigAttribute>();
        //match all of /admin/**  a/b/**
        while (ite.hasNext()) {

            String resURL = ite.next();
            urlMatcher = new AntPathRequestMatcher(resURL);

            if (urlMatcher.matches(request)||StringUtils.equals(request.getRequestURI(),resURL)) {
                attrSet.addAll(attrMap.get(resURL));
            }
        }

        if(!attrSet.isEmpty()){
            return attrSet;
        }
        return null;
    }

//    @Override
    public void afterPropertiesSet() throws Exception {
        loadResourceDefine() ;
    }

}